/*
 *  Copyright (C) 2011 yudi wibisono (yudi1975@gmail.com)
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.upi.cs;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 *
 * @author yudi wibisono
 */
public class Util {

    //untuk mensort


    private static class ItemComparable implements Comparator<Item>{
	@Override
	public int compare(Item o1, Item o2) {
		return (o1.seq<o2.seq ? -1 : (o1.seq>o2.seq ? 1 : 0));
	}
     }


    private static class ItemComparableReverse implements Comparator<Item>{
	@Override
	public int compare(Item o1, Item o2) {
		return (o1.seq<o2.seq ? 1 : (o1.seq>o2.seq ? -1 : 0));
	}
     }

    public class Item {
        int seq;           //urutan tidak boleh hilang (transaksi jenis 2 cenderung berada di belakang)
        String session;
        String itemNo;
        String transType;
    }

    public void removeLast3Item (String inputFile) {
        //untuk mempersiapkan file test
        //membuang (memisahkan tepatnya), 3 objek pada transaksi terakhir sebuah session

      Logger log = Logger.getLogger("edu.cs.upi.tweetmining");
      String inputFileWoExt = inputFile.substring(0, inputFile.lastIndexOf('.')); //without ext
      String namaFileOutputTest = inputFileWoExt+"_withoutLast3Item.txt";  //nanti menjadi file test
      String namaFileOutputEval = inputFileWoExt+"_last3Item.txt";         //nanti menjadi file eval
      try {
            PrintWriter pwTest = new PrintWriter(namaFileOutputTest);
            PrintWriter pwEval = new PrintWriter(namaFileOutputEval);
            
            FileInputStream fstream = new FileInputStream(inputFile);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;

            int cc=0;
            Item itm;
            String session="";
            ArrayList<Item> alItem ;   //list item per session
            alItem = new ArrayList<Item>();
            while ((strLine = br.readLine()) != null)   {
                cc++;
                System.out.println(cc);
                String[] temp;
                temp = strLine.split("\\|");
                if (!temp[0].equals(session)) {
                    //ganti session
                    session = temp[0];
                    //sort
                    Collections.sort(alItem, new ItemComparableReverse());

                    //ambil 3 item terbawah
                    HashMap<String,Item> hm3Item = new HashMap<String,Item>();
                    Item tempItm;
                    int numItem=0;
                    for (Item itmLoop: alItem)  //sudah disort dari besar ke kecil (urutan trans aka cc)
                    {                        
                        tempItm = hm3Item.get(itmLoop.itemNo);
                        if (tempItm == null) {  //belum ada, add
                            //asumsikan data oroginal juga sudah terurut berdasarkan transtype
                            hm3Item.put(itmLoop.itemNo,itmLoop);
                            numItem++;
                        }
                        if (numItem==3) {break;}
                    }
                    
                    //save tiga item tersebut ke dalam eval
                    for (Map.Entry<String,Item> entry : hm3Item.entrySet())
                    {
                        Item it=entry.getValue();
                        alItem.remove(it); //buang dari alItem
                        pwEval.println(it.session + "|" + it.itemNo + "|" + it.transType);
                    }
                    pwEval.flush();

                    //save item yg sudah dibuang 3 obj kedaam test
                    //sort berdasarkan urutan asal
                    Collections.sort(alItem, new ItemComparable());
                    for (Item itm2: alItem)
                    {
                        pwTest.println(itm2.session + "|" + itm2.itemNo + "|" + itm2.transType);
                    }
                    pwTest.flush();
                    //buat hashmap baru
                    alItem = new ArrayList<Item>();
                }
                
                itm = new Item();                
                itm.seq = cc;
                itm.itemNo = temp[1];
                itm.session = temp[0];
                itm.transType = temp[2];
                alItem.add(itm);
                //testing
                //if ( (cc % 1000) ==0) {
                //    pwEval.flush();
                //    pwTest.flush();
                //    break;  //testing 1000 dulu dulu
                //}
            }

            pwEval.close();
            pwTest.close();
            br.close();
            in.close();
            fstream.close();
            } catch (Exception e) {
                e.printStackTrace();
                log.severe(e.toString());
       }


    }

    public void removeDupTrans(String inputFile) {
          //input: file mentah
          //output: menjadikan mirip file test (dalam satu session hanya ada satu produk, kalau duplikasi
          //hanya dipilih trans tertinggi
          //tujuannya untuk menyiapkan file test versi sendiri untuk mengukur kinerja algoritma
          //warning: untuk membuat file test, perlu diambil 3 item transaksi terakhir dulu baru diremove dup-nya, kalau
          //kalau tidak, bisa ada informasi yang hilang.jadi untuk buat file test


          //baca per baris, load data per item (gunakan hashmap supaya tdk duplikat)
          //kalau sudah ada, cek jenis transaksinya, kalau trans 0 bisa diganti 1, 1 bisa dignati 2 else biarkan
          //saat session ganti, tulis ke fileoutput

      

      Logger log = Logger.getLogger("edu.cs.upi.tweetmining");
      String inputFileWoExt = inputFile.substring(0, inputFile.lastIndexOf('.')); //without ext
      String namaFileOutput = inputFileWoExt+"_noDuplicate.txt";
      try {
            PrintWriter pw = new PrintWriter(namaFileOutput);
            FileInputStream fstream = new FileInputStream(inputFile);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            int cc=0;
            Item itm;
            String session="";
            HashMap<String,Item> hmItem=null;
            hmItem = new  HashMap<String,Item>();
            while ((strLine = br.readLine()) != null)   {
                cc++;
                System.out.println(cc);
                String[] temp;
                temp = strLine.split("\\|");
                if (!temp[0].equals(session)) {
                    //ganti session

                    session = temp[0];
                    
                    //siapkan untuk disort
                    ArrayList<Item> alItem = new ArrayList<Item>(); //pindahkan ke array list untuk disort
                    for (Map.Entry<String,Item> entry : hmItem.entrySet())
                    {
                        Item it=entry.getValue();
                        alItem.add(it);
                    }
                    Collections.sort(alItem, new ItemComparable());
                    
                    //tulis ke file
                    for (Item itm2: alItem)
                    {
                        pw.println(itm2.session + "|" + itm2.itemNo + "|" + itm2.transType);
                    }

                    pw.flush();





                    //buat hashmap baru
                    hmItem = new  HashMap<String,Item>();
                }

                itm = hmItem.get(temp[1]);
                if (itm==null) {  //belum ada
                    itm = new Item();
                    hmItem.put(temp[1], itm);
                    itm.seq = cc;
                    itm.itemNo = temp[1];
                    itm.session = temp[0];
                    itm.transType = temp[2];
                }
                else {
                    //sudah ada, update kalau jenis trans lebih tinggi
                    if (temp[2].equals("1") && itm.transType.equals("0")) {
                                itm.transType = "1"; //replace
                                itm.seq = cc;
                    } else
                    if (temp[2].equals("2") && !itm.transType.equals("2")) {
                                itm.transType = "2"; //replace
                                itm.seq = cc;

                    } 
                }
                //testing
                //if ( (cc % 1000) ==0) {
                    //pw.flush();
                 //   break;  //testing 1000 dulu dulu
                //}
            }

            

            pw.close();
            br.close();
            in.close();
            fstream.close();
            } catch (Exception e) {
                e.printStackTrace();
                //log.severe(e.toString());
       }
     }

      
      public static void main(String args[]) {
          //testing
          Util u = new Util();
          //u.removeDupTrans("F:\\dataminingcup\\task1\\transact_train_sessionwithtransOrder.txt");
          u.removeLast3Item("F:\\dataminingcup\\task1\\transact_train_sessionwithtransOrder.txt");
      }
}
